﻿using Lg.Core.Form;
using Newtonsoft.Json.Linq;
using System.Data;
using System.Diagnostics;

namespace Lg.Core.Extensions.Form
{
    public static class Extensions
    {
        private static object locker = new object();
        public static List<IType>? TestValue(this List<IType> list)
        {
            foreach (IType type in list)
            {
                type.Verify();
            }
            return list;
        }
        /// <summary>
        /// 传入一个List<FormItem>,把其转为List<ITYpe>,Value没有值
        /// </summary>
        /// <param name="formItems"></param>
        /// <returns>List<IType>类型,Value无值</returns>
        public static List<IType> ToITypes(this List<FormItem> formItems)
        {
            var itypes = new List<IType>();
            foreach (var formItem in formItems)
            {
                string? d = ClearTypeDefaultValue(formItem.Data!);
                var itype = TypeFactory.GetType(formItem.TypeName, d);
                if (itype != null)
                {
                    itypes.Add(itype);
                }
                else
                {
                    throw new Lg.Core.Exceptions.LgException($"未能创建类型名称为:{formItem.TypeName}的对像实体");
                }
            }
            return itypes;
        }
        /// <summary>
        /// 传入一个List<FormItem>,把其转为List<ITYpe>,Value有值
        /// </summary>
        /// <param name="formItems">自定义表单模板</param>
        /// <param name="jsonStr">学生的数据</param>
        /// <returns>IType类型,Value有值</returns>
        /// <exception cref="LgException"></exception>
        public static List<IType> ToITypes(this List<FormItem> formItems, string jsonStr,ref List<FormData> formDatas)
        {
            JObject formData = jsonStr.ToJobject();
            List<IType> types = new List<IType>();//表单字段集合
            foreach (var formItem in formItems)
            {
                string? data = ClearTypeDefaultValue(formItem.Data!);
                var iType = TypeFactory.GetType(formItem.TypeName, data);
                if (iType != null)
                {
                    FormData? fd=iType.SetValue(formData);
                    if (fd != null)
                    {
                        formDatas.Add(fd);
                    }
                    types.Add(iType);
                }
                else
                {
                    throw new Lg.Core.Exceptions.LgException($"未能创建类型名称为:{formItem.TypeName}的对像实体");
                }
            }
            return types;
        }

        /// <summary>
        /// 用于初始获取可展示、导出、查询的自定义表单字段参数
        /// 获取和生成初始字段配置数据，包括，显示列、导出列、查询列等数据
        /// </summary>
        /// <param name="itypes"></param>
        /// <param name="formConfigs"></param>
        /// <returns></returns>
        public static List<TypeParam>? GetTypeParams(this List<IType> itypes)
        {
            List<TypeParam> list = new List<TypeParam>();
            foreach (var type in itypes)
            {
                var fd = type.GetValue();
                if (fd != null)
                {
                    list.Add(new TypeParam
                    {
                        ExportName = fd.ExportName,
                        Name = fd.Name,
                        Title = fd.Title,
                        IsExport = false,
                        IsShow = false,
                        IsWhere = false
                    });
                }
            }
            return list.Count > 0 ? list : null;
        }
        public static List<FormData> SetValues(this List<IType> itypes, JObject obj)
        {
            List<FormData> formData = new List<FormData>();
            foreach (var item in itypes)
            {
                var fd = item.SetValue(obj);
                if (fd != null)
                {
                    formData.Add(item.GetValue());
                }
            }
            return formData;
        }
        public static List<FormData> GetValues(this List<IType> itypes)
        {
            List<FormData> formData = new List<FormData>();
            foreach (var item in itypes)
            {
                var fd = item.GetValue();
                if (fd != null)
                {
                    formData.Add(fd);
                }
            }
            return formData;
        }
        private static string? ClearTypeDefaultValue(string data)
        {
            var tempData = JObject.Parse(data);
            tempData["Value"] = "";
            return Convert.ToString(tempData);
        }

        public static List<SearchParam> BuildSearchParams(this List<IType> types, List<SearchParam> where, ref string model)
        {
            if (types == null || where == null)
            {
                throw new Exception("");
            }
            JObject models = new JObject();
            List<SearchParam> forms = new List<SearchParam>();
            List<FormData> formDatas = new List<FormData>();

            foreach (var item in types)
            {
                var temp = item.GetValue();
                if (temp != null)
                {
                    formDatas.Add(temp);
                }
            }

            foreach (var search in where)
            {
                var names = search.Name.Split(',');
                if (names.Length > 1)
                {
                    forms.Add(search);
                }
                else
                {
                    var exist = formDatas.Any(t =>
                    {
                        return search.Name == t.Name;
                    });
                    if (exist)
                    {
                        forms.Add(search);
                    }
                    else
                    {
                        models[search.Name] = search.Value;
                    }
                }

            }
            model = models.ToJsonString();
            return forms;
        }

        /// <summary>
        /// 做3件事,新建列,填充每行该列的数据,对每行数据进行筛选
        /// </summary>
        /// <param name="types"></param>
        /// <param name="table"></param>
        /// <param name="where"></param>
        /// <param name="dataColumnName"></param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public static DataTable ProcessDataToTableColumn(this List<IType> types, DataTable table, List<SearchParam> where, string dataColumnName = "FormData")
        {
            #region [1、判断指定的数据列是否存在]
            if (table.Columns[dataColumnName] == null)
            {
                throw new Exception("指定的数据列不存在");
            }
            #endregion
            #region [2、获取所有数据字段的列表并将自定义表单的字段名插入到table列]
            foreach (IType type in types)
            {
                FormData fd = type.GetValue();
                if (fd != null)
                {
                    table.Columns.Add(fd.Name);
                }
            }
            #endregion

            #region[3、逐行处理自定义表单数据并插入到对应的列,最后删除table的原数据列]
            var afterSearch = table.Clone();

            List<Task> tasks = new List<Task>();
            int page = 0;
            int step = 500;
            while (page * step < table.Rows.Count)
            {
                page++;
                int start = (page - 1) * step;
                int end = page * step - 1;
                if (table.Rows.Count <= (page * step))
                {
                    end = table.Rows.Count - 1;
                }
                var task = Task.Run(() =>
                  {
                      Stopwatch sw = new Stopwatch();
                      sw.Start();
                      for (int i = start; i < end; i++)
                      {
                          DataRow dr = table.Rows[i];
                          string? strData = Convert.ToString(dr[dataColumnName]);
                          if (strData != null)
                          {
                              var obj = strData.ToJobject();
                              var formDatas = new List<FormData>();

                              foreach (IType type in types)
                              {
                                  try
                                  {
                                      var fd = type.SetValue(obj);
                                      if (fd != null)
                                      {
                                          dr[fd.Name!] = fd.Value;
                                          formDatas.Add(fd);
                                      }
                                  }
                                  catch
                                  {

                                  }

                              }
                            #region [数据筛选]
                            //if (where != null && where.Any())
                            //{
                            //    bool success = true;
                            //    foreach (var search in where)
                            //    {
                            //        if (!string.IsNullOrEmpty(search.Value))
                            //        {
                            //            var exist = formDatas.Any(f =>
                            //            {
                            //                bool flag = search.Name.Split(',').Contains(f.Name);
                            //                if (search.Key == "模糊匹配")
                            //                {
                            //                    flag = flag && f.Value.Contains(search.Value);
                            //                }
                            //                else if (search.Key == "精确匹配")
                            //                {
                            //                    flag = flag && f.Value == search.Value;
                            //                }
                            //                else
                            //                {
                            //                    flag = flag && f.Value == search.Value;
                            //                }
                            //                return flag;
                            //            });
                            //            if (!exist)
                            //            {
                            //                success = false;
                            //                break;
                            //            }
                            //        }

                            //    }
                            //    if (success)
                            //    {
                            //        afterSearch.ImportRow(dr);
                            //    }
                            //}

                            //else
                            //{
                            //    afterSearch.ImportRow(dr);
                            //}
                            #endregion
                          }
                      }
                      sw.Stop();
                      Console.WriteLine(sw.ElapsedMilliseconds);
                  });
                tasks.Add(task);
            }
            Task.WaitAll(tasks.ToArray());
            table.Columns.Remove(dataColumnName);
            #endregion
            return table;
        }

        public static DataTable ProcessTable(this List<IType> types, DataTable table, List<SearchParam> where, bool isFillColumn = false,string sort="Id desc", string dataColumnName = "FormData")
        {
            #region [1、判断指定的数据列是否存在]
            if (table.Columns[dataColumnName] == null)
            {
                throw new Exception("指定的数据列不存在");
            }
            #endregion

            #region [2、当需要将自定义表单数据插入到table时获取所有数据字段的列表并将自定义表单的字段名插入到table列]
            if (isFillColumn)
            {
                foreach (IType type in types)
                {
                    FormData fd = type.GetValue();
                    if (fd != null)
                    {
                        table.Columns.Add(fd.Name);
                    }
                }
            }
            #endregion

            #region [3]复制原始表头，执行数据查询并将符合条件的数据插入到新表中用于返回
            var resTable = table.Clone();
            List<DataRow> rows = new List<DataRow>();
            List<Task> tasks = new List<Task>();
            int page = 0;
            int step = 2000;
            while (page * step < table.Rows.Count)
            {
                page++;
                int start = (page - 1) * step;
                int end = page * step - 1;
                if (table.Rows.Count <= (page * step))
                {
                    end = table.Rows.Count - 1;
                }
                tasks.Add(Task.Run(() =>
                {
                    for (int i = start; i <= end; i++)
                    {
                        lock (table.Rows.SyncRoot)
                        {
                            DataRow dr = table.Rows[i];
                            string? strData = Convert.ToString(dr[dataColumnName]);
                            JObject? obj = strData?.ToJobject();
                            if (obj != null)
                            {
                                bool success = true;
                                if (where != null && where.Any())
                                {
                                    foreach (var search in where)
                                    {
                                        bool flag = false;
                                        string[] names = search.Name.Split(',');
                                        foreach (string name in names)
                                        {
                                            string? val = obj[name]?.ToString();
                                            if (!string.IsNullOrEmpty(val))
                                            {
                                                if (val.Contains("{"))
                                                {
                                                    val = JObject.Parse(val)["value"]?.ToString();
                                                }
                                                if (val != null)
                                                {
                                                    if (search.Key == "模糊匹配")
                                                    {
                                                        flag = flag || val.ToLower().Contains(search.Value.ToLower());
                                                    }
                                                    else
                                                    {
                                                        flag = flag || (val == search.Value);
                                                    }
                                                }
                                            }
                                        }
                                        if (!flag)
                                        {
                                            success = false;
                                            break;
                                        }
                                    }

                                }
                                if (success)
                                {
                                    if (isFillColumn)
                                    {
                                        List<FormData> formDatas = types.SetValues(obj);
                                        foreach (var fd in formDatas)
                                        {
                                            try
                                            {
                                                dr[fd.Name!] = fd.Value;
                                            }
                                            catch
                                            {

                                            }

                                        }
                                    }
                                    resTable.ImportRow(dr);    
                                }
                            }
                        }
                        
                    }
                }));
            }
            Task.WaitAll(tasks.ToArray());
            GC.Collect();
            #endregion

            #region [4]当返回表中有数据则进行排序并返回
            if (resTable.Rows.Count > 0)
            {
                DataView dv = resTable.DefaultView;
                dv.Sort = sort;
                return dv.ToTable();
            }
            else
            {
                return resTable;
            }
            #endregion

        }
    
        /// <summary>
        /// 把tablerow,提起为可以保存数据库的formdata
        /// </summary>
        /// <param name="types"></param>
        /// <param name="row"></param>
        /// <returns></returns>
        public static Dictionary<string,dynamic> GetSaveDbValue(this List<IType> types,DataRow row)
        {
            var dict=new Dictionary<string,dynamic>();
            foreach (var item in types)
            {
                if (row.Table.Columns.IndexOf(item.Name)!=-1)
                {
                    var value = row[item.Name]?.ToString();
                    item.GetSaveDbValue(dict, value);
                } 

            }
            return dict;
        }
    }
}